using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Scripting;
using Microsoft.Scripting.Actions;
using Microsoft.Scripting.Internal;
using Microsoft.Scripting.Hosting;
using Nua;
using System.Threading;

// TODO:// hack because TopReflectedPackage is internal
using IronPython.Runtime.Types;

namespace Nua.Runtime
{
    public class NuaOps
    {
        private static TopReflectedPackage _topPackage;

        static NuaOps()
        {
            DynamicHelpers.GetDynamicTypeFromType = NuaOps.GetDynamicTypeFromType;
            DynamicTypeBuilder.TypeInitialized += new EventHandler<TypeCreatedEventArgs>(NuaTypeCustomizer.OnTypeInit);
        }

        public static NuaTable MakeTable()
        {
            return new NuaTable();
        }


        public static object GetIndex(NuaTable self, object key)
        {
            if (self.Keys.Contains(key))
                return self[key];
            else
            {
                return new object();
            }
        }

        public static void SetIndex(NuaTable self, object key, object value)
        {
            self[key] = value;
        }

        public static DynamicType GetDynamicTypeFromType(Type ty) 
        {
            if (ty == null) throw new NotImplementedException();

            DynamicType ret = DynamicType.GetDynamicType(ty);
            if (ret != null) return ret;

            ret = ReflectedTypeBuilder.Build(ty);

            return SaveDynamicType(ty, ret);
        }   

        public static DynamicType SaveDynamicType(Type ty, DynamicType dt) {
            return DynamicType.SetDynamicType(ty, dt);
        }

        public static void Print(object o)
        {
            Console.WriteLine(o);
        }

        public static double Add(double a, double b)
        {
            return a + b;
        }

        public static bool LessThan(object x, object y)
        {
            if (x is int && y is int) { return ((int)x) < ((int)y); }
            if (x is double && y is double) { return ((double)x) < ((double)y); }
            if (x is string && y is string) { return ((string)x).CompareTo((string)y) < 0; }

            throw new NotImplementedException();
        }

        public static bool LessThanEquals(object x, object y)
        {
            if (x is int && y is int) { return ((int)x) <= ((int)y); }
            if (x is double && y is double) { return ((double)x) <= ((double)y); }
            if (x is string && y is string) { return ((string)x).CompareTo((string)y) <= 0; }

            throw new NotImplementedException();
        }

        public static bool GreaterThan(object x, object y)
        {
            if (x is int && y is int) { return ((int)x) > ((int)y); }
            if (x is double && y is double) { return ((double)x) > ((double)y); }
            if (x is string && y is string) { return ((string)x).CompareTo((string)y) > 0; }

            throw new NotImplementedException();
        }

        public static bool GreaterThanEquals(object x, object y)
        {
            if (x is int && y is int) { return ((int)x) >= ((int)y); }
            if (x is double && y is double) { return ((double)x) >= ((double)y); }
            if (x is string && y is string) { return ((string)x).CompareTo((string)y) >= 0; }

            throw new NotImplementedException();
        }

        public static object NuaEquals(object x, object y)
        {
            if (x is int && y is int) { return ((int)x) == ((int)y); }
            if (x is double && y is double) { return ((double)x) == ((double)y); }
            if (x is string && y is string) { return ((string)x).Equals((string)y); }

            throw new NotImplementedException();
        }

        public static Exception NotImplementedError(string format, params object[] args) 
        {
            return new NotImplementedException(string.Format(format, args));
        }

        public static readonly object NotImplemented;

        public static object IfTest(object o1, object o2)
        {
            if ((o1 == null) && (o2 == null))
				return true;
			if ((o1 == null) || (o2 == null))
				return false;
			if (o1.GetType() == typeof(double) && o2.GetType() == typeof(double))
				return ((double)o1) == ((double)o2);
			if (o1.GetType() == typeof(double) && o2.GetType() == typeof(bool))
			{
				o1 = true;
				return ((bool)o1) == ((bool)o2);
			}
			if (o1.GetType() == typeof(bool) && o2.GetType() == typeof(double))
			{
				o2 = true;
				return ((bool)o1) == ((bool)o2);
			}
			if (o1.GetType() == typeof(string) && o2.GetType() == typeof(string))
				return (((string)o1).CompareTo(((string)o2)) == 0);
			if (o1.GetType() == typeof(bool) && o2.GetType() == typeof(bool))
				return ((bool)o1) == ((bool)o2);
			else
				throw new NotImplementedException();
        }

    }
}
